// 使用递归的方式实现深拷贝


//定义函数
function MyDeepClone(value,hash = new WeakMap()){ //value:要拷贝的源数据    hash:已拷贝的对象备忘录,防止做循环引用的
    
    // 如果是基础数据类型或者函数,则直接返回
    if(value === null || typeof value !== 'object')  return value

    // 常用的特殊对象
    if(value instanceof Date) return new Date(value)
    if(value instanceof RegExp) return new RegExp(value)
    
    // 解决循环引用 obj.a = obj,剪断循环引用,防止函数无限递归
    if(hash.has(value)) return hash.get(value)
    
    //走到这一步,说明传入的value不是基础数据类型,也不是函数以及以上的特殊对象    
    const result = new value.constructor() //创建一个该value的空壳子
    hash.set(value,result) //将可能会导致无限递归的对象存入hash中

    // 遍历value的属性,这里会遗漏到map,set,因为map和set的key是不可枚举的
    for(let key in value){ //遍历value的所有属性
        if(value.hasOwnProperty(key)){ //判断当前对象本身（而不是原型链上的）是否拥有某个属性
            result[key] = MyDeepClone(value[key],hash) //递归拷贝value的属性
        }
    }
    // 遍历value的属性,这里会遗漏到map,set,因为map和set的key是不可枚举的
    if (value instanceof Map) {
        value.forEach((v, k) => result.set(k, MyDeepClone(v, hash)));
      } else if (value instanceof Set) {
        value.forEach(v => result.add(MyDeepClone(v, hash)));
      }
    
    return result
    }

// 测试
const obj = {
    name: 'John',
    age: 30,
    friends: {
        name: 'Jane',
        age: 25
    }
}

let obj2=MyDeepClone(obj)
console.log('obj2',obj2)
